import path from "node:path";
import { $console } from "bknd/utils";
import type { MiddlewareHandler } from "hono";
import open from "open";
import { fileExists, getRelativeDistPath } from "../../utils/sys";
import type { App } from "App";

export const PLATFORMS = ["node", "bun"] as const;
export type Platform = (typeof PLATFORMS)[number];

export async function serveStatic(server: Platform): Promise<MiddlewareHandler> {
   const onNotFound = (path: string) => {
      $console.debug("Couldn't resolve static file at", path);
   };

   switch (server) {
      case "node": {
         const m = await import("@hono/node-server/serve-static");
         const root = getRelativeDistPath() + "/static";
         $console.debug("Serving static files from", root);
         return m.serveStatic({
            // somehow different for node
            root,
            onNotFound,
         });
      }
      case "bun": {
         const m = await import("hono/bun");
         const root = path.resolve(getRelativeDistPath(), "static");
         $console.debug("Serving static files from", root);
         return m.serveStatic({
            root,
            onNotFound,
         });
      }
   }
}

export async function startServer(
   server: Platform,
   app: App,
   options: { port: number; open?: boolean },
) {
   const port = options.port;
   $console.log(`Using ${server} serve`);

   switch (server) {
      case "node": {
         // https://github.com/honojs/node-server/blob/main/src/response.ts#L88
         const serve = await import("@hono/node-server").then((m) => m.serve);
         serve({
            fetch: (req) => app.fetch(req),
            port,
         });
         break;
      }
      case "bun": {
         Bun.serve({
            fetch: (req) => app.fetch(req),
            port,
         });
         break;
      }
   }

   const url = `http://localhost:${port}`;
   $console.info("Server listening on", url);

   if (options.open) {
      await open(url);
   }
}

export async function getConfigPath(filePath?: string) {
   if (filePath) {
      const config_path = path.resolve(process.cwd(), filePath);
      if (await fileExists(config_path)) {
         return config_path;
      } else {
         $console.error(`Config file could not be resolved: ${config_path}`);
         process.exit(1);
      }
   }

   const exts = ["", ".js", ".ts", ".mjs", ".cjs", ".json"];
   const paths = exts.map((e) => `bknd.config${e}`);
   for (const p of paths) {
      const _p = path.resolve(process.cwd(), p);
      if (await fileExists(_p)) {
         return _p;
      }
   }

   return;
}

export function getConnectionCredentialsFromEnv() {
   const dbUrl = process.env.DB_URL;
   const dbToken = process.env.DB_TOKEN;
   return dbUrl ? { url: dbUrl, authToken: dbToken } : undefined;
}
